package com.naiterui.ehp.bs.doctor.service.notify.impl;

import java.util.List;

import com.naiterui.ehp.bp.domain.DrFollowUpRecord;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.naiterui.ehp.bp.bo.recommend.param.RecomInfoParamBO;
import com.naiterui.ehp.bp.domain.Doctor;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bp.utils.biz.AppJumpProtocol;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bp.utils.lang.StringUtil;
import com.naiterui.ehp.bp.utils.notice.AppNoticeUtil;
import com.naiterui.ehp.bp.utils.notice.AppPushUtil;
import com.naiterui.ehp.bs.doctor.exception.ExceptionCodes;
import com.naiterui.ehp.bs.doctor.service.IDoctorService;
import com.naiterui.ehp.bs.doctor.service.IPAService;
import com.naiterui.ehp.bs.doctor.service.notify.INotifyService;
import com.naiterui.ehp.bs.doctor.utils.ImageUrlUtil;
import com.naiterui.ehp.bs.doctor.utils.PropertyValueConstants;
import com.naiterui.ehp.bs.doctor.utils.SMSUtil;
import com.naiterui.ehp.bs.doctor.utils.SMSUtil.Template;


/**
 * 医生通知相关业务实现
 *
 * @author Amber
 * @since 1.0.0
 */
@Service
public class AdNotifyServiceImpl implements INotifyService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdNotifyServiceImpl.class);

    @Autowired
    private IDoctorService doctorService;
    @Autowired
    private IPAService paService;

    @Override
    public void notifyRecordStatusChange(Long doctorId, Integer recordStatus, String failReason) throws BusinessException {

        Doctor doctor = doctorService.get(doctorId);
        // 判断目标用户账号正常
        if (doctor == null || doctor.getAccountStatus() == 1) {
            throw new BusinessException(ExceptionCodes.DOCTOR_ACCOUNT_ERROR);
        }

        // 系统消息类型
        Integer messageType = 0;
        Template smsTemplate = null;
        switch (recordStatus) {
            // 备案通过
            case Doctor.RECORD_STATUS_SUCCESS:
                messageType = PropertyValueConstants.TEMPLATE_TYPE_RECORD_SUCCESS;
                smsTemplate = Template.RECORD_SUCCESS;
                break;
            // 备案失败
            case Doctor.RECORD_STATUS_FAIL:
                messageType = PropertyValueConstants.TEMPLATE_TYPE_RECORD_FAIL;
                smsTemplate = Template.RECORD_FAIL;
                break;
            // 要求备案
            case Doctor.RECORD_STATUS_REQUIREMENT:
                messageType = PropertyValueConstants.TEMPLATE_TYPE_RECORD_REQUIRED;
                smsTemplate = Template.RECORD_REQUIRED;
                break;
            case Doctor.RECORD_STATUS_NO:
                messageType = PropertyValueConstants.TEMPLATE_TYPE_RECORD_STATUS_NO;
                smsTemplate = Template.RECORD_NO;
                break;
            default:
                break;
        }

        // 系统消息对应push文案
        String pushMessage = PropertyValueConstants.RECORD_PUSH_MSG_MAP.get(messageType);

        // 系统消息对应notice文案
        String noticeMessage = PropertyValueConstants.RECORD_NOTICE_MSG_MAP.get(messageType);
        LOGGER.info("发送系统通知，内容为 {}", noticeMessage);

        // 消息体为空,类型非法
        if (StringUtils.isBlank(pushMessage) || StringUtils.isBlank(noticeMessage) || messageType == 0 || smsTemplate == null) {
            return;
        }

        // 发短信
        SMSUtil.asyncSendSMS(doctor.getPhone(), smsTemplate, failReason);

        try {

            /** 组织备案状态Notice **/
            // 系统消息 notice图标路径，为适应不同环境，由业务系统获取当前环境图片地址
            String noticePath = ImageUrlUtil.genNoticePath(ConfigUtil.getString("img.notice.dynamic"));
            //（医生端优化1.1）备案失败消息增加了原因，修改了页面跳转页地址
            AppJumpProtocol protocol = AppJumpProtocol.DR_HOME;

            AppNoticeUtil.DrDynamicInfo dynamicInfo = null;
            if (recordStatus.equals(Doctor.RECORD_STATUS_SUCCESS)) {
                // 构建notice
                dynamicInfo = new AppNoticeUtil.DrDynamicInfo(noticeMessage, System.currentTimeMillis(),
                    AppJumpProtocol.DR_CA_SIGN.parse(), noticePath, null,
                    recordStatus);
                //push消息需要跳转页（跳转到消息中心）
                protocol = AppJumpProtocol.DR_DYNAMIC;
            } else if (recordStatus.equals(Doctor.RECORD_STATUS_FAIL)) {
                // 构建notice
                dynamicInfo = new AppNoticeUtil.DrDynamicInfo(noticeMessage, System.currentTimeMillis(),
                    AppJumpProtocol.DR_HOME.parse(), noticePath, null,
                    recordStatus);
                //push消息需要跳转页（跳转到消息中心），以及消息体转换
                pushMessage = StringUtil.templateFormat(pushMessage,failReason);
                protocol = AppJumpProtocol.DR_DYNAMIC;
            }

            // 保存系统消息到个人账户
            paService.savePaWithNotice(doctorId, failReason, messageType, dynamicInfo);
            // push消息
            AppPushUtil.sendDrPush(ConfigUtil.getString("push.message.server"), doctorId, pushMessage, protocol, failReason);
        } catch (Exception e) {
            LOGGER.error("备案状态变更通知失败，医生id：{},变更状态：{},系统通知类型：{},push文案：{},短信文案：{}", doctorId, recordStatus, messageType, pushMessage,
                         smsTemplate.getTemplateId(), e);
        }
    }

    @Override
    public void notifyAuthStatusChange(long doctorId, int newStatus, String failReason) {
        try {
            Doctor doctor = doctorService.get(doctorId);
            // push消息类型
            Integer messageType = 0;
            // 判断目标用户账号正常
            if (doctor == null || doctor.getAccountStatus() == 1) {
                return;
            }
            Integer paType = null;
            switch (newStatus) {
                // 认证通过
                case Doctor.AUTH_STATUS_SUCCESS:
                    paType = PropertyValueConstants.TEMPLATE_TYPE_AUTH_SUCCESS;
                    messageType = PropertyValueConstants.TEMPLATE_TYPE_AUTH_NEW_SUCCESS;
                    break;
                // 认证失败
                case Doctor.AUTH_STATUS_REJECTED:
                    paType = PropertyValueConstants.TEMPLATE_TYPE_AUTH_FALD;
                    messageType = PropertyValueConstants.TEMPLATE_TYPE_AUTH_NEW_FAIL;
                    break;
                // 首次提交认证、再次提交认证
                case Doctor.AUTH_STATUS_AUDITING:
                    // 首次提交（且已上传资质）
                    paType = PropertyValueConstants.TEMPLATE_TYPE_AUTH_APPLY;
                    break;
                default:
                    break;
            }
            // 没匹配的系统消息类型，不处理
            if (null == paType) {
                return;
            }

            // push消息发送
            String pushMessage = PropertyValueConstants.AUTH_PUSH_MSG_MAP.get(messageType);
            String pushMsgServer = ConfigUtil.getString("push.message.server");
            AppPushUtil.sendDrPush(pushMsgServer, doctorId, StringUtil.templateFormat(pushMessage,failReason), AppJumpProtocol.DR_DYNAMIC, failReason);

            // 系统消息发送 notice图标路径，为适应不同环境，由业务系统获取当前环境图片地址
            String noticePath = ImageUrlUtil.genNoticePath(ConfigUtil.getString("img.notice.dynamic"));
            // 系统Notice文案
            String noticeContent = paService.getContentByType(paType, failReason);

            //格式化认证通过后的消息
            if (Doctor.AUTH_STATUS_SUCCESS == newStatus){
                noticeContent = paService.formatAuthSuccess(noticeContent,doctorId);
            }
            LOGGER.info("  系统消息：newStatus={}, noticeContent={}", newStatus, noticeContent);
            // 构建notice
            AppNoticeUtil.DrDynamicInfo dynamicInfo = new AppNoticeUtil.DrDynamicInfo(noticeContent, System.currentTimeMillis(),
                                                                                      AppJumpProtocol.DR_DYNAMIC.parse(), noticePath, newStatus,
                                                                                      null);

            paService.savePaWithNotice(doctorId, failReason, paType, dynamicInfo);
        } catch (Exception e) {
            LOGGER.error("认证状态变更通知失败，医生id：{},最新状态：{}，失败原因:{}", doctorId, newStatus, failReason, e);

        }
    }


    /**
     * 发送购药通知 全购、取消没有有push消息，少购既有push消息也有系统通知
     *
     * @param recomBOList
     *
     * @Author heichou
     * @Date 2018年10月18日
     * @since 3.4.0
     * INotifyService.notifyRecomBuy()
     */
    @Override
    public void notifyRecomBuy(List<RecomInfoParamBO> recomBOList) {
        try {
            // 系统消息 notice图标路径，为适应不同环境，由业务系统获取当前环境图片地址
            String noticePath = ImageUrlUtil.genNoticePath(ConfigUtil.getString("img.notice.dynamic"));
            // 根据推荐id获取处方笺患者信息
            for (RecomInfoParamBO recomInfoParamBO : recomBOList) {
                //状态 13:少购 14：全购  15：取消
                Integer paType = recomInfoParamBO.getType();
                Long doctorId = recomInfoParamBO.getDoctorId();
                String patientName = recomInfoParamBO.getPatientName();
                Long recommendId = recomInfoParamBO.getRecommendId();
                //状态是否正确
                Boolean typeBoolean = paType == null || !(PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_PARTBUY == paType || PropertyValueConstants
                        .TEMPLATE_TYPE_RECOMMEND_ALLBUY == paType || PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_CANCELBUY == paType);
                if (doctorId == null || recommendId == null || typeBoolean) {
                    continue;
                }
                LOGGER.info("INotifyService.notifyRecomBuy doctorId:{},recommendId:{},paType:{}", doctorId, recommendId, paType);
                Doctor doctor = doctorService.getDoctorById(doctorId);
                // 判断目标用户账号正常
                if (doctor == null || doctor.getAccountStatus() == 1) {
                    LOGGER.info("INotifyService.notifyRecomBuy 目标参数异常 doctorId:{},recommendId:{},paType:{}", doctorId, recommendId, paType);
                    continue;
                }
                String recomId = String.valueOf(recommendId);
                // 系统Notice文案
                String noticeContent = paService.getContentByType(paType, patientName);
                if (paType == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_ALLBUY) {
                    noticeContent = PropertyValueConstants.RECORD_BUY_NOTICE_MSG_MAP.get(PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_ALLBUY);
                } else if (paType == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_CANCELBUY) {
                    noticeContent = PropertyValueConstants.RECORD_BUY_NOTICE_MSG_MAP.get(PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_CANCELBUY);
                }
                // 构建notice
                AppNoticeUtil.DrDynamicInfo dynamicInfo;

                dynamicInfo = new AppNoticeUtil.DrDynamicInfo(noticeContent, System.currentTimeMillis(), AppJumpProtocol.DR_DYNAMIC.parse(recomId),
                                                              noticePath);
                paService.saveNoticeWithLinkParam(doctorId, patientName, recomId, paType, dynamicInfo);
                // 发送push消息
                if (paType == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_PARTBUY) {
                    AppPushUtil.sendDrPush(ConfigUtil.getString("push.message.server"), doctorId, noticeContent, AppJumpProtocol.DR_HOME, "");
                }
            }
        } catch (Exception e) {
            LOGGER.error("发送患者少购通知失败，recomBOList：{}", JsonMapper.toJson(recomBOList), e);
        }
    }

    @Override
    public void sendReferralNotice(Long doctorId, Long patientId, String doctorName, String patientName) throws BusinessException {
        String noticeContent = String.format(ConfigUtil.getString("message.referralNoticeThatDay.todoc.text"), doctorName, patientName);
        String noticePath = ImageUrlUtil.genNoticePath(ConfigUtil.getString("img.notice.dynamic"));
        // 构建notice
        AppNoticeUtil.DrDynamicInfo dynamicInfo = new AppNoticeUtil.DrDynamicInfo(noticeContent, System.currentTimeMillis(),
                                                                                  AppJumpProtocol.DR_DYNAMIC.parse(), noticePath);

        try {
            paService.saveNoticeWithLinkParam(doctorId, new String[]{doctorName, patientName},
                                                   new String[]{patientName, patientId.toString()},
                                                   PropertyValueConstants.TEMPLATE_TYPE_REFERRALNOTICE,
                                                   dynamicInfo);
        } catch (Exception e) {
            LOGGER.error("复诊提醒医生--发送通知异常");
            throw new BusinessException(ExceptionCodes.SEND_REFFERALNOTICE_ERROR);
        }

    }

    @Override
    public void sendConsultCommentNotice(Long doctorId, Long commentId) throws BusinessException {
        try {
            paService.saveNoticeWithLinkParam(doctorId, new String[]{},
                                                new String[]{commentId + ""},
                                                PropertyValueConstants.TEMPLATE_TYPE_CONSULT_COMMENT_NOTIFY,
                                                null);
        } catch (Exception e) {
            LOGGER.error("会话评价--发送通知异常");
            throw new BusinessException(ExceptionCodes.SEND_CONSULT_COMMENT_ERROR);
        }
    }

    @Override
    public void sendFollowUpNotice(Long doctorId, Long followUpId, Integer type) throws BusinessException {
        try {
            String typeMsg = DrFollowUpRecord.TYPE_QA == type ? "问卷" : "复诊";
            paService.saveNoticeWithLinkParam(doctorId, new String[] {typeMsg}, new String[] {followUpId + "",String.valueOf(type)},
                PropertyValueConstants.TEMPLATE_TYPE_FOLLOW_UP_NOTIFY, null);
        } catch (Exception e) {
            LOGGER.error("患者填写随访表单--发送通知异常");
            throw new BusinessException(ExceptionCodes.SEND_CONSULT_COMMENT_ERROR);
        }
    }
}
